package com.youkeyi.ddy.cloud.basic.pub.tag.controller;


import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.youkeyi.ddy.cloud.basic.pub.mapping.entity.SysMapping;
import com.youkeyi.ddy.cloud.basic.pub.mapping.param.BusinessQueryParam;
import com.youkeyi.ddy.cloud.basic.pub.mapping.service.SysMappingService;
import com.youkeyi.ddy.cloud.basic.pub.tag.entity.SysTag;
import com.youkeyi.ddy.cloud.basic.pub.tag.service.SysTagService;
import com.youkeyi.ddy.cloud.common.api.basic.pub.tag.PublicTagCloudService;
import com.youkeyi.ddy.cloud.common.api.basic.pub.tag.dto.*;
import com.youkeyi.ddy.cloud.common.api.basic.pub.tag.param.*;
import com.youkeyi.ddy.cloud.common.constant.YoukeyiDdyCloudBasicPublicConstant;
import com.youkeyi.ddy.cloud.common.enums.ResponseCodeEnum;
import com.youkeyi.ddy.cloud.common.response.ResponseContent;
import com.youkeyi.ddy.cloud.common.utils.SimpleUUidUtils;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * <p>
 * 标签表 前端控制器
 * </p>
 *
 * @author xiawang.liu
 * @since 2024-03-07
 */
@Service
public class SysTagController implements PublicTagCloudService {

    @Autowired
    private SysTagService sysTagService;
    @Autowired
    private SysMappingService sysMappingService;

    @Override
    public PublicTagListCloudDto query(PublicTagQueryCloudParam param) {
        PublicTagListCloudDto dto = new PublicTagListCloudDto();
        if (null == param) {
            dto.setErrorMessage(ResponseCodeEnum.PARAMETER_ILLEGAL.getMessage());
            return dto;
        }

        if (CollectionUtils.isNotEmpty(param.getTagPrimaryKeys())) {
            param.getTagPrimaryKeys().removeAll(Collections.singleton(null));
        }
        if (CollectionUtils.isNotEmpty(param.getCorpKeys())) {
            param.getCorpKeys().removeAll(Collections.singleton(null));
        }
        if (CollectionUtils.isNotEmpty(param.getCodes())) {
            param.getCodes().removeAll(Collections.singleton(null));
        }
        if (CollectionUtils.isNotEmpty(param.getParentKeys())) {
            param.getParentKeys().removeAll(Collections.singleton(null));
        }

        QueryWrapper<SysTag> wrapper = new QueryWrapper<>();
        wrapper.lambda()
                .in(CollectionUtils.isNotEmpty(param.getTagPrimaryKeys()), SysTag::getPrimaryKey, param.getTagPrimaryKeys())
                .in(CollectionUtils.isNotEmpty(param.getCorpKeys()), SysTag::getCorpKey, param.getCorpKeys())
                .like(StringUtils.isNotBlank(param.getNameFuzzy()), SysTag::getName, param.getNameFuzzy())
                .in(CollectionUtils.isNotEmpty(param.getCodes()), SysTag::getCode, param.getCodes())
                .in(CollectionUtils.isNotEmpty(param.getParentKeys()), SysTag::getParentKey, param.getParentKeys())
                .ne(SysTag::getIsDeleted, YoukeyiDdyCloudBasicPublicConstant.SYSTEM_YES_OR_NO_YES.value())
        ;

        Page<SysTag> page = new Page<>();
        if (null != param.getCurrentPage() && null != param.getPageSize()) {
            page.setCurrent(param.getCurrentPage());
            page.setSize(param.getPageSize());
        } else {
            page.setCurrent(1);
            page.setSize(99999999);
        }
        Page<SysTag> tagList = sysTagService.page(page, wrapper);
        if (CollectionUtils.isNotEmpty(tagList.getRecords())) {
            dto.setTotal(tagList.getTotal());

            List<PublicTagListItemCloudDto> items = new ArrayList<>();
            tagList.getRecords().forEach(tag -> {
                PublicTagListItemCloudDto item = new PublicTagListItemCloudDto();
                item.setTagPrimaryKey(tag.getPrimaryKey());
                item.setCorpKey(tag.getCorpKey());
                item.setName(tag.getName());
                item.setCode(tag.getCode());
                item.setIcon(tag.getIcon());
                item.setIconColor(tag.getIconColor());
                item.setLevel(tag.getLevel());
                item.setParentKey(tag.getParentKey());
                item.setPath(tag.getPath());
                item.setDesc(tag.getDesc());
                item.setRemark(tag.getRemark());
                item.setIsDeleted(tag.getIsDeleted());
                item.setIsDeletedName(YoukeyiDdyCloudBasicPublicConstant.SYSTEM_YES_OR_NO.getName(item.getIsDeleted()));
                item.setCreateTime(tag.getCreateTime() != null ? tag.getCreateTime().getTime() : null);
                item.setCreateUserKey(tag.getCreateUserKey());
                item.setCreateUserName(tag.getCreateUserName());
                item.setUpdateTime(tag.getUpdateTime() != null ? tag.getUpdateTime().getTime() : null);
                item.setUpdateUserKey(tag.getUpdateUserKey());
                item.setUpdateUserName(tag.getUpdateUserName());
                items.add(item);
            });
            dto.setRows(items);
        }
        dto.setSuccessMessage(ResponseCodeEnum.SUCCESS.getMessage());
        return dto;
    }

    @Override
    public List<PublicTagTreeItemCloudDto> queryTree(PublicTagQueryTreeCloudParam param) {
        QueryWrapper<SysTag> wrapper = new QueryWrapper<>();
        wrapper.lambda()
                .like(StringUtils.isNotBlank(param.getTagPrimaryKey()), SysTag::getPath, param.getTagPrimaryKey())
                .ne(SysTag::getIsDeleted, YoukeyiDdyCloudBasicPublicConstant.SYSTEM_YES_OR_NO_YES.value())
        ;
        List<SysTag> tags = sysTagService.list(wrapper);

        List<PublicTagTreeItemCloudDto> tree = new ArrayList<>();
        tags.forEach(tag -> {
            PublicTagTreeItemCloudDto item = new PublicTagTreeItemCloudDto();
            item.setTagPrimaryKey(tag.getPrimaryKey());
            item.setTagCode(tag.getCode());
            item.setName(tag.getName());
            item.setIcon(tag.getIcon());
            item.setIconColor(tag.getIconColor());
            item.setParentKey(tag.getParentKey());
            item.setDesc(tag.getDesc());
            item.setRemark(tag.getRemark());
            tree.add(item);
        });

        // 转树
        Map<String, List<PublicTagTreeItemCloudDto>> tagByParentKeyMaps = tree.stream().collect(Collectors.groupingBy(PublicTagTreeItemCloudDto::getParentKey));
        tree.forEach(item -> item.setTagItems(tagByParentKeyMaps.get(item.getTagPrimaryKey())));
        if (StringUtils.isBlank(param.getTagPrimaryKey())) {
            return tree.stream().filter(v -> v.getTagPrimaryKey().equals(param.getTagPrimaryKey())).collect(Collectors.toList());
        }
        return tree;
    }

    @Override
    public ResponseContent create(PublicTagCreateCloudParam param) {
        ResponseContent rc = new ResponseContent();
        if (null == param || StringUtils.isBlank(param.getName())) {
            rc.setErrorMessage(ResponseCodeEnum.PARAMETER_ILLEGAL.getMessage());
            return rc;
        }
        SysTag tag = new SysTag();
        tag.setPrimaryKey(SimpleUUidUtils.getUuid());
        tag.setCorpKey(param.getCorpKey());
        tag.setName(param.getName());
        tag.setCode(StringUtils.isNotBlank(param.getCode()) ? param.getCode() : String.format("TAG-%s", System.currentTimeMillis()));
        tag.setIcon(param.getIcon());
        tag.setIconColor(param.getIconColor());
        tag.setDesc(param.getDesc());
        tag.setRemark(param.getRemark());
        tag.setIsDeleted(YoukeyiDdyCloudBasicPublicConstant.SYSTEM_YES_OR_NO_NO.value());
        tag.setCreateUserKey(param.getCreateUserKey());
        tag.setCreateUserName(param.getCreateUserName());
        tag.setCreateTime(new Date());

        // 构造父级数据
        tag.setLevel(0);
        tag.setParentKey("");
        tag.setPath(String.format("|%s|", tag.getPrimaryKey()));
        if (StringUtils.isNotBlank(param.getParentKey())) {
            QueryWrapper<SysTag> queryWrapper = new QueryWrapper<>();
            queryWrapper.lambda().eq(SysTag::getParentKey, param.getParentKey());
            SysTag parentTag = sysTagService.getOne(queryWrapper);
            if (null != parentTag && StringUtils.isNotBlank(parentTag.getPrimaryKey())) {
                tag.setLevel(parentTag.getLevel() + 1);
                tag.setParentKey(parentTag.getPrimaryKey());
                tag.setPath(String.format("%s|", parentTag.getPath()));
            }
        }

        boolean save = sysTagService.save(tag);
        if (!save) {
            rc.setErrorMessage(ResponseCodeEnum.FAIL.getMessage());
            return rc;
        }
        rc.setSuccessMessage(ResponseCodeEnum.SUCCESS.getMessage());
        rc.setKey(tag.getPrimaryKey());
        return rc;
    }

    @Override
    public ResponseContent update(PublicTagUpdateCloudParam param) {
        ResponseContent rc = new ResponseContent();
        if (null == param || StringUtils.isBlank(param.getTagPrimaryKey())) {
            rc.setErrorMessage(ResponseCodeEnum.PARAMETER_ILLEGAL.getMessage());
            return rc;
        }

        UpdateWrapper<SysTag> wrapper = new UpdateWrapper<>();
        wrapper.lambda()
                .eq(SysTag::getPrimaryKey, param.getTagPrimaryKey());
        SysTag tag = new SysTag();
        tag.setPrimaryKey(param.getTagPrimaryKey());
        tag.setName(param.getName());
        tag.setCode(param.getCode());
        tag.setIcon(param.getIcon());
        tag.setIconColor(param.getIconColor());
        tag.setPath(param.getCode());
        tag.setDesc(param.getDesc());
        tag.setRemark(param.getRemark());
        tag.setUpdateUserKey(param.getUpdateUserKey());
        tag.setUpdateUserName(param.getUpdateUserName());
        tag.setUpdateTime(new Date());
        boolean save = sysTagService.update(tag, wrapper);
        rc.setSuccessMessage(ResponseCodeEnum.SUCCESS.getMessage());
        if (!save) {
            rc.setErrorMessage(ResponseCodeEnum.FAIL.getMessage());
            return rc;
        }
        return rc;
    }

    @Override
    public ResponseContent delete(PublicTagDeleteCloudParam param) {
        ResponseContent rc = new ResponseContent();
        if (null == param || CollectionUtils.isEmpty(param.getTagPrimaryKeys())) {
            rc.setErrorMessage(ResponseCodeEnum.PARAMETER_ILLEGAL.getMessage());
            return rc;
        }
        UpdateWrapper<SysTag> wrapper = new UpdateWrapper<>();
        wrapper.lambda()
                .in(SysTag::getPrimaryKey, param.getTagPrimaryKeys());

        SysTag tag = new SysTag();
        tag.setIsDeleted(YoukeyiDdyCloudBasicPublicConstant.SYSTEM_YES_OR_NO_YES.value());
        tag.setUpdateUserKey(param.getUpdateUserKey());
        tag.setUpdateUserName(param.getUpdateUserName());
        tag.setUpdateTime(new Date());
        boolean save = sysTagService.update(tag, wrapper);
        rc.setSuccessMessage(ResponseCodeEnum.SUCCESS.getMessage());
        if (!save) {
            rc.setErrorMessage(ResponseCodeEnum.FAIL.getMessage());
        }
        return rc;
    }





    @Override
    public ResponseContent bind(PublicTagBindCloudParam param) {
        ResponseContent rc = new ResponseContent();
        if (null == param || CollectionUtils.isEmpty(param.getBindItems())) {
            rc.setErrorMessage(ResponseCodeEnum.PARAMETER_ILLEGAL.getMessage());
            return rc;
        }
        List<SysMapping> tagCreateParams = new ArrayList<>();
        param.getBindItems().forEach(item -> {
            if (StringUtils.isNotBlank(item.getTagPrimaryKey()) && StringUtils.isNotBlank(item.getTargetPrimaryKey())) {
                SysMapping tagMapping = new SysMapping();
                tagMapping.setPrimaryKey(SimpleUUidUtils.getUuid());
                tagMapping.setMappingType(YoukeyiDdyCloudBasicPublicConstant.PUBLIC_MAPPING_TYPE_TAG_TARGET.value());
                tagMapping.setSourceKey(item.getTagPrimaryKey());
                tagMapping.setTargetKey(item.getTargetPrimaryKey());
                tagMapping.setCreateUserKey(param.getCreateUserKey());
                tagMapping.setCreateUserName(param.getCreateUserName());
                tagCreateParams.add(tagMapping);
            }
        });
        if (CollectionUtils.isNotEmpty(tagCreateParams)) {
            sysMappingService.businessCreate(tagCreateParams);
        }
        rc.setSuccessMessage(ResponseCodeEnum.SUCCESS.getMessage());
        return rc;
    }

    @Override
    public ResponseContent unbind(PublicTagUnbindCloudParam param) {
        ResponseContent rc = new ResponseContent();
        if (null == param || CollectionUtils.isEmpty(param.getUnbindItems())) {
            rc.setErrorMessage(ResponseCodeEnum.PARAMETER_ILLEGAL.getMessage());
            return rc;
        }

        List<SysMapping> mappings = new ArrayList<>();
        param.getUnbindItems().forEach(item -> {
            if (StringUtils.isNotBlank(item.getTagPrimaryKey()) && StringUtils.isNotBlank(item.getTargetPrimaryKey())) {
                SysMapping mapping = new SysMapping();
                mapping.setMappingType(YoukeyiDdyCloudBasicPublicConstant.PUBLIC_MAPPING_TYPE_TAG_TARGET.value());
                mapping.setSourceKey(item.getTagPrimaryKey());
                mapping.setTargetKey(item.getTargetPrimaryKey());
                mappings.add(mapping);
            }
        });
        rc.setSuccessMessage(ResponseCodeEnum.SUCCESS.getMessage());
        if (CollectionUtils.isNotEmpty(mappings)) {
            boolean save = sysMappingService.businessDelete(mappings);
            if (!save) {
                rc.setErrorMessage(ResponseCodeEnum.FAIL.getMessage());
            }
        }
        return rc;
    }

    @Override
    public PublicTagQueryBindListCloudDto queryBind(PublicTagQueryBindCloudParam param) {
        PublicTagQueryBindListCloudDto dto = new PublicTagQueryBindListCloudDto();
        if (null == param) {
            dto.setErrorMessage(ResponseCodeEnum.PARAMETER_ILLEGAL.getMessage());
            return dto;
        }

        if (CollectionUtils.isNotEmpty(param.getTargetPrimaryKeys())) {
            param.getTargetPrimaryKeys().removeAll(Collections.singleton(null));
        }

        BusinessQueryParam queryMappingParam = new BusinessQueryParam();
        queryMappingParam.setMappingType(YoukeyiDdyCloudBasicPublicConstant.PUBLIC_MAPPING_TYPE_TAG_TARGET.value());
        queryMappingParam.setKeyType(YoukeyiDdyCloudBasicPublicConstant.PUBLIC_MAPPING_KEY_TYPE_TARGET.value());
        queryMappingParam.setKeys(param.getTargetPrimaryKeys());
        List<SysMapping> sysMappings = sysMappingService.businessQuery(queryMappingParam);
        if (CollectionUtils.isNotEmpty(sysMappings)) {
            List<String> tagKeys = sysMappings.stream().map(SysMapping::getSourceKey).collect(Collectors.toList());
            if (CollectionUtils.isNotEmpty(tagKeys)) {
                QueryWrapper<SysTag> wrapper = new QueryWrapper<>();
                wrapper.lambda()
                        .in(CollectionUtils.isNotEmpty(tagKeys), SysTag::getPrimaryKey, tagKeys)
                        .ne(SysTag::getIsDeleted, YoukeyiDdyCloudBasicPublicConstant.SYSTEM_YES_OR_NO_YES.value())
                ;
                List<SysTag> tags = sysTagService.list(wrapper);
                Map<String, SysTag> tagMap = new HashMap<>();
                if (CollectionUtils.isNotEmpty(tags)) {
                    tagMap.putAll(tags.stream().collect(Collectors.toMap(SysTag::getPrimaryKey, Function.identity(), (k1, k2) -> k1)));
                }

                List<PublicTagQueryBindListItemCloudDto> items = new ArrayList<>();
                sysMappings.forEach(sysMapping -> {
                    SysTag tag = tagMap.get(sysMapping.getSourceKey());
                    if (null != tag) {
                        PublicTagQueryBindListItemCloudDto item = new PublicTagQueryBindListItemCloudDto();
                        item.setTargetPrimaryKey(sysMapping.getTargetKey());
                        item.setTagPrimaryKey(tag.getPrimaryKey());
                        item.setCorpKey(tag.getCorpKey());
                        item.setCode(tag.getCode());
                        item.setName(tag.getName());
                        item.setIcon(tag.getIcon());
                        item.setIconColor(tag.getIconColor());
                        item.setCreateUserKey(sysMapping.getCreateUserKey());
                        item.setCreateUserName(sysMapping.getCreateUserName());
                        item.setCreateTime(null != sysMapping.getCreateTime() ? sysMapping.getCreateTime().getTime() : null);
                        items.add(item);
                    }
                });
                dto.setRows(items);
            }
        }
        dto.setSuccessMessage(ResponseCodeEnum.SUCCESS.getMessage());
        return dto;
    }
}
